package cn.edu.buaa.sei.jdat.vt;

import java.util.List;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import com.cocotingo.snail.dispatcher.DispatchQueue;
import com.cocotingo.snail.dispatcher.Dispatcher;

import cn.edu.buaa.sei.jdat.model.Element;
import cn.edu.buaa.sei.jdat.search.IndexItem;
import cn.edu.buaa.sei.jdat.search.Query;
import cn.edu.buaa.sei.jdat.search.SearchController;
import cn.edu.buaa.sei.jdat.search.exception.InvalidQueryException;
import cn.edu.buaa.sei.jdat.vt.MainView.Tab;
import cn.edu.buaa.sei.jdat.vt.res.Resources;
import cn.edu.buaa.sei.jdat.vt.widgets.JavaElementListView;
import cn.edu.buaa.sei.jdat.vt.widgets.TextBox;

// TODO: implement search view
public class SearchView extends Tab {
	
	TextBox textBox;
	JavaElementListView resultList;
	Query query;
	
	private static final int LIST_MAX_SIZE = 256;
	private final DispatchQueue search_queue;
	
	public SearchView(MainView owner) {
		super(owner);
		query = new Query();
		search_queue = new DispatchQueue();
		
		addSubview(textBox = new TextBox(30, 30, 400, 50) {
			{
				setFont(Resources.FONT_BIG_PLAIN);
				getTextField().getDocument().addDocumentListener(new DocumentListener() {
					@Override
					public void removeUpdate(DocumentEvent arg0) {
						textChanged(getText());
					}
					@Override
					public void insertUpdate(DocumentEvent arg0) {
						textChanged(getText());
					}
					@Override
					public void changedUpdate(DocumentEvent arg0) {
						textChanged(getText());
					}
				});
			}
		});
		
		addSubview(resultList = new JavaElementListView(30, 85, 400, 400));
		
	}
	
	private void textChanged(final String text) {
		
		// Execute "search" in another thread, so it won't block the ui.
		
		search_queue.execute(new Runnable() {
			@Override
			public void run() {
				
				SearchController sc = getOwner().getSearchController();
				query.set(text);
				try {
					query.validate();
				} catch (InvalidQueryException e) {
					// clear list
					Dispatcher.executeAndWaitAndSyncWithGUI(new Runnable() {
						@Override
						public void run() {
							resultList.removeAllElements();
						}
					});
				}
				List<IndexItem> result = sc.getHints(query);
				if (result == null)
					return;
				int allcount = 0;
				for (IndexItem it : result) {
					allcount += it.size();
				}
				
				int count = 0;
				final Object[] items = new Object[LIST_MAX_SIZE > allcount ? allcount : LIST_MAX_SIZE];
				for (IndexItem it : result) {
					for (Element e : it) {
						if (count >= LIST_MAX_SIZE)
							break;
						items[count] = e;
						count++;
					}
				}
				
				// update ui.
				Dispatcher.executeAndWaitAndSyncWithGUI(new Runnable() {
					@Override
					public void run() {
						resultList.SetElements(items);
					}
				});
			}
		});
		
	}

	@Override
	protected void activated() {
	}

	@Override
	protected void deactivated() {
	}

	@Override
	protected void layout() {
	}

}
